#ifndef __BUILD_TLV_H__
#define __BUILD_TLV_H__

static int TLV_MSG_SEQENCE = 1; // TLV 消息序列号，从1开始递增，取值范围为0x00000000~0x7FFFFFFF

#define TLV_MSG_SEQENCE_MIN = 0x01;        // TLV 消息序列号最小值
#define TLV_MSG_SEQENCE_MAX = 0x7FFFFFFF;  // TLV 消息序列号最大值



/**
 *  TLV 消息命令类型，即此消息是要发送的消息还是接受的消息
 **/
enum TLV_COMMAND_ID
{
    SEND_MSG = 0x0002,  // 发送消息
    RECV_MSG = 0x0003,  // 接受消息
};

/**
 *  TLV 消息的类型，每个 TLV_BODY 都有一个类型
 **/
typedef enum TLV_BODY_TYPE
{
    TLV_BODY_TYPE_STRING = 0x00,  // 字符串型
    TLV_BODY_TYPE_INT    = 0x01,  // 整数型
} TLV_BODY_TYPE;

/**
 *  TLV 消息头部，长度共28位
 **/
struct TLV_HEAD
{
    int   tlvHeadLength;           // TLV 消息总长度，即TLV_HEAD + TLV_BODY
    short tlvHeadVersion;          // TLV 消息版本号
    short tlvHeadCommandId;        // TLV 消息命令类型
    int   tlvHeadSeqence;          // TLV 消息序列号
    char  tlvHeadCheckNumber[16];  // TLV 消息校验
};

/**
 *  TLV 消息体
 *
 *  实际上tlvBodyValueLength和tlvBodyValue在代码中并未引用
 *  而是通过build_tlv_body()将这部分数值组建到buffer里面
 *  这样做的目的是：
 *      1.为了减少代码含量，将重复部分封装到build_tlv_body()里面，
 *          用户只关心tlvBodyType、tlvBodyTag和需要组建的value值即可。
 *          里面的一些大小端转化用户也无需关注。根据需要传入实际值即可。
 *      2.在头文件中便于查看TLV_BODY的结构
 **/
struct TLV_BODY
{
    int   tlvBodyType;             // TLV 消息值的类型（TLV_BODY_TYPE）

    short tlvBodyTag;              // TLV 消息tag（消息编号id），根据此tag解析value
    short tlvBodyValueLength;      // TLV 消息值的长度
    char  tlvBodyValue[0];         // TLV 消息值
};


/**
 *  TLV 消息
 **/
struct TLV_MSG
{
    struct TLV_HEAD tlvHead;
    struct TLV_BODY tlvBody;
};

/* 组建TLV消息(消息头 + 消息体) */
void *build_tlv_msg(struct TLV_MSG *tlvMsg, char *buffer, void *value);

#endif